<template>
  <div class="chart-item">
    <chart-header
      v-if="!config.hideBar && instance"
      :title="title"
      :name="id"
    >
      <template #tool>
        <slot name="tool" />
      </template>
    </chart-header>
    <div
      :id="id"
      style="flex: 1"
      :peakvalue="peakvalue"
    />
  </div>
</template>

<script setup name="DataChart">
  import Highcharts from '@/plugins/highcharts'
  import ChartHeader from '@/views/analyse/header/ChartHeader'
  import useChartsStore from '@/store/modules/charts'
  import useChartOptions from '@/common/hooks/chartOptions'
  import { cloneDeep, ceil, floor } from 'lodash'
  import ci from '@/common/chartInstances'
  import { sortBy } from 'lodash'

  const props = defineProps({
    id: {
      type: String,
      default: 'linecharts'
    },
    title: {
      type: String,
      default: '星座图'
    },
    data: {
      type: Array,
      default: () => []
    },
    config: {
      type: Object,
      default: () => ({
        type: 'trend', // trend 动态图 static 静态图 ccdf 需要排序的ccdf图
        chart: {}
      })
    }
  })

  // 传递的峰值 xf
  const peakvalue = ref(null)
  const emit = defineEmits(['transferData'])
  const instance = ref(null)
  const curViewData = ref([])
  const chartsStore = useChartsStore()
  const showNum = computed(() => props.config.viewNum || chartsStore.viewNum)
  const { chartOptions } = useChartOptions()

  const transferData = arr => {
    emit('transferData', peakvalue, arr)
  }

  const xValHandler = (val) => {
    if (typeof val === 'number') {
      return Number(val.toFixed(2))
    }
    return val
  }

  const getXValues = data => {
    if (data.length === 0) {
      peakvalue.value = null
      return
    }
    const arr = new Array(6).fill(1).map(() => ({ cur: 0, diff: 999 }))
    for (let item of data) {
      const [x, y] = item
      arr.forEach((m, i) => {
        const num = 0.1 / Math.pow(10, i)
        if (Math.abs(num - y) < m.diff) {
          m.diff = Math.abs(num - y)
          m.cur = x
        }
      })
    }
    peakvalue.value = xValHandler(data[data.length - 1][0])
    let newArr = []
    arr.forEach(item => {
      const value = xValHandler(parseFloat(item.cur))
      newArr.push(value > 20 ? '--' : value + 'dB')
    })
    transferData(newArr)
  }

  const getSliceData = (data, type, start, end) => {
    if (type === 'mutiTrend') {
      return data.map(item => {
        return item.slice(start, end)
      })
    } else if (type === 'ccdf') {
      return end > data.length ? data.slice(start, data.length) : data.slice(start, end)
    } else {
      return data.slice(start, end)
    }
  }

  const getStaticData = (data, start, type) => {
    const prefix = []
    while(start < 0) {
      prefix.push(null)
      start++
    }
    if (type === 'ccdf') {
      return sortBy(data, [0])
    }
    return prefix.concat(data.slice(start))
  }

  // 生成这一帧的图像
  const generateViewData = (data, start) => {
    const { type, viewNum } = props.config
    const len = type === 'mutiTrend' ? data[0].length : data.length
    if (viewNum === 'all') {
      return getStaticData(data, start, type)
    }
    let temp = []
    if (start + showNum.value >= len) {
      temp = getSliceData(data, type, -showNum.value)
    } else {
      temp = getSliceData(data, type, start, start + showNum.value)
    }
    if (type === 'ccdf') {
      temp = sortBy(temp, [0])
    }
    return temp
  }

  // 更新图表
  const updateChart = (start = 0) => {
    if (!instance.value || !instance.value.series) {
      return
    }
    const { type } = props.config
    curViewData.value = generateViewData(props.data, start)
    instance.value.series?.forEach((s, i) => {
      if (type === 'mutiTrend') {
        s.setData(curViewData.value[i], true, false)
      } else {
        s.setData(curViewData.value, true, false)
      }
    })
  }

  const generateOptions = () => {
    const options = cloneDeep(chartOptions.value)
    const { chart } = props.config
    if (!chart) {
      return options
    } else {
      setYRange(chart)
      return chart
    }
  }

  const hasYRange = options => {
    if (!options) {
      return true
    }
    if (options.yAxis.min !== undefined || options.yAxis.max !== undefined) {
      return true
    }
  }

  const setYRange = options => {
    if (props.config.type !== 'trend' || hasYRange(options)) {
      return
    }
    let min = Infinity,
      max = -Infinity
    props.data.forEach(item => {
      const yNum = item[1] ? item[1] : item
      if (min > yNum) {
        min = yNum
      }
      if (max < yNum) {
        max = yNum
      }
    })
    options.yAxis.min = floor(min)
    options.yAxis.max = ceil(max)
  }
  const start = computed(() => props.config.start ?? chartsStore.start)
  watch(() => curViewData.value,
    val => {
      if (props.config.type === 'ccdf') {
        getXValues(val)
      }
    }
  )
  // 配置变化 TODO watch太多，逻辑臃肿，需要重构
  watch(() => props.config.chart, (val) => {
    console.log('配置改变了')
    val && instance.value.update(val, true)
    updateChart(start.value)
  })
  watch(() => props.data, val => {
    updateChart(start.value)
  })
  watch(
    () => chartsStore.start,
    start => {
      if (props.config.type == 'static') {
        return
      }
      updateChart(start)
    }
  )
  watch(
    () => props.config.start,
    start => {
      updateChart(start)
    }
  )

  const initHighChart = () => {
    const chartOptions = generateOptions()
    instance.value = new Highcharts.Chart(props.id, chartOptions)
    ci.set(instance.value, props.id)
    // 插入一帧初始数据
    updateChart(start.value)
  }

  defineExpose({
    instance,
    updateChart
  })

  onMounted(() => {
    initHighChart()
  })

  onUnmounted(() => {
    ci.del(props.id)
  })
</script>

<style lang="scss" scoped></style>
